﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.Office.Interop.Word;
using Puzzler.Common;
using Puzzler.Common.Exceptions;

namespace Puzzler.Plugin.Interface
{
    public abstract class PuzzleIOHandler<TModel, TUpgrate> : IPuzzleIOHandler, IModelable<TModel> where TModel : PuzzleModel where TUpgrate : PuzzleIOUpgrateHandler<TModel>
    {
        public TModel Model { get; private set; }
        /// <summary>
        /// Upgrate handler if version does not match
        /// </summary>
        public TUpgrate IoUpgrateHandler { get; private set; }
        /// <summary>
        /// File Format Version for XML
        /// </summary>
        public abstract int XmlFormatVersion { get; }
        public abstract int BinaryFormatVersion { get; }

        protected PuzzleIOHandler(TModel model)
        {
            Model = model;
            IoUpgrateHandler = (TUpgrate) Activator.CreateInstance(typeof (TUpgrate), Model);
        }

        public void SaveToXml(XElement element)
        {
            element.Add(new XAttribute("version", XmlFormatVersion));

            element.Add(new XAttribute(PuzzleModel.CaptionProperty.Name, Model.Caption));
            element.Add(new XAttribute(PuzzleModel.CommentProperty.Name, Model.Comment ?? ""));
            element.Add(new XAttribute(PuzzleModel.StateProperty.Name, Model.State));

            SaveToXElement(element);
        }

        public void LoadFromXml(XElement element)
        {
            Model.Caption = element.ReadFromAttribute(PuzzleModel.CaptionProperty.Name);
            Model.Comment = element.ReadFromAttribute(PuzzleModel.CommentProperty.Name);
            Model.State = element.ReadFromAttribute(PuzzleModel.StateProperty.Name, s => (PuzzleState)Enum.Parse(typeof(PuzzleState), s));

            int version = element.ReadFromAttribute("version", Int32.Parse);
            if (version != XmlFormatVersion)
            {
                if (!IoUpgrateHandler.UpgrateXml(element, version, XmlFormatVersion))
                    throw new PuzzlerIOException("XML Part for plugin (io handler '" + GetType().Name +
                                                 "') does not match with version. Found was " + version + ", needed is: " +
                                                 XmlFormatVersion);
                return; //Objects already filled by upgrater
            }

            LoadFromXElement(element);
        }

        public void SaveToBinary(StreamWriter writer)
        {
            
        }

        public void LoadFromBinary(StreamReader reader)
        {
            
        }

        #region Plugin Action

        public virtual void OnInitialized()
        {
        }

        public virtual void OnDone()
        {
        }

        public virtual void OnActivated()
        {
        }

        public virtual void OnDeactivated()
        {
        }

        #endregion

        /// <summary>
        /// Save content to xelement
        /// <b>Caption already saved</b>
        /// </summary>
        protected abstract void SaveToXElement(XElement xElement);
        /// <summary>
        /// Load content from xelement
        /// <b>Caption already loaded</b>
        /// </summary>
        protected abstract void LoadFromXElement(XElement xElement);
    }
}
